package com.sl.ms.carriage.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.stream.StreamUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.system.SystemUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sl.ms.base.api.common.AreaFeign;
import com.sl.ms.carriage.domain.constant.CarriageConstant;
import com.sl.ms.carriage.domain.dto.CarriageDTO;
import com.sl.ms.carriage.domain.dto.WaybillDTO;
import com.sl.ms.carriage.domain.enums.EconomicRegionEnum;
import com.sl.ms.carriage.entity.CarriageEntity;
import com.sl.ms.carriage.enums.CarriageExceptionEnum;
import com.sl.ms.carriage.mapper.CarriageMapper;
import com.sl.ms.carriage.service.CarriageService;
import com.sl.ms.carriage.utils.CarriageUtils;
import com.sl.transport.common.exception.SLException;
import com.sl.transport.common.util.ObjectUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class CarriageServiceImpl extends ServiceImpl<CarriageMapper, CarriageEntity> implements CarriageService {
    private final AreaFeign areaFeign;

    public CarriageServiceImpl(AreaFeign areaFeign) {
        this.areaFeign = areaFeign;
    }

    @Override
    public CarriageDTO saveOrUpdate(CarriageDTO carriageDto) {

        //判断模版类型 是否属于经济区类型模版
        if(ObjectUtil.notEqual(carriageDto.getTemplateType(),  CarriageConstant.ECONOMIC_ZONE)){
            // 判断是否是经济区类型模版
            CarriageEntity byTemplateType = this.findByTemplateType(carriageDto.getTemplateType());
            //判断模版存不存在存在的话直接保存
            if(ObjectUtil.isEmpty(byTemplateType)){
                return getCarriageDTO(carriageDto);
            }
            //ID是否为空 是否为经济区模版
            if(ObjectUtil.isEmpty(carriageDto.getId())){
                throw new SLException(CarriageExceptionEnum.NOT_ECONOMIC_ZONE_REPEAT);
            }
            //要修改的ID不能和已存在的ID相等
            if(ObjectUtil.notEqual(carriageDto.getId(), byTemplateType.getId())){
                throw new SLException(CarriageExceptionEnum.NOT_ECONOMIC_ZONE_REPEAT);
            }
            return getCarriageDTO(carriageDto);
        }
        //查询出经济区互籍的 集合
        List<CarriageEntity> carriageEntityList = findAllByTemplateType();
        //是经济区模版 查询 判读 和已存在的 模版ID 不能重复

        List<String> collectCarriageCityList = carriageEntityList.stream()
                .map(CarriageEntity::getAssociatedCity)
                .map(carriageCity -> StrUtil.split(carriageCity, ","))
                .flatMap(StreamUtil::of)
                .collect(Collectors.toList());
        Collection<String> intersection = CollUtil.intersection(collectCarriageCityList, carriageDto.getAssociatedCityList());
        if(CollUtil.isNotEmpty(intersection)){
            throw new SLException(CarriageExceptionEnum.ECONOMIC_ZONE_CITY_REPEAT);
        }
        return getCarriageDTO(carriageDto);
    }

    @NotNull
    private CarriageDTO getCarriageDTO(CarriageDTO carriageDto) {
        CarriageEntity entity = CarriageUtils.toEntity(carriageDto);
        this.saveOrUpdate(entity);
        return CarriageUtils.toDTO(entity);
    }

    public List<CarriageEntity> findAllByTemplateType() {
        LambdaQueryWrapper<CarriageEntity> wrapper = Wrappers.<CarriageEntity>lambdaQuery()
                .eq(CarriageEntity::getTemplateType, CarriageConstant.ECONOMIC_ZONE);
        List<CarriageEntity> list = this.list(wrapper);
        return list;
    }
    @Override
    public List<CarriageDTO> findAll() {
        LambdaQueryWrapper<CarriageEntity> wrapper = Wrappers.<CarriageEntity>lambdaQuery();
        List<CarriageEntity> list = this.list(wrapper);

        return list.stream().map(CarriageUtils ::toDTO).collect(Collectors.toList());
    }

    @Override
    public CarriageDTO compute(WaybillDTO waybillDTO) {
        //查运费末班
        CarriageEntity carriageEntity = findCarriageTemplate(waybillDTO);
        //计算重量
        double v = computeWeight(waybillDTO, carriageEntity);
        double expense = carriageEntity.getFirstWeight() + carriageEntity.getContinuousWeight() * (v - 1);
        expense = NumberUtil.round(expense, 1).doubleValue();
        CarriageDTO dto = CarriageUtils.toDTO(carriageEntity);
        dto.setExpense(expense);

        return dto;
    }
    public double computeWeight(WaybillDTO waybillDTO,CarriageEntity carriageEntity){
        //查询体积'
        Integer volume = waybillDTO.getVolume();
        if (ObjectUtil.isEmpty(volume)){
            Integer measureLong = waybillDTO.getMeasureLong();
            Integer measureWidth = waybillDTO.getMeasureWidth();
            Integer measureHigh = waybillDTO.getMeasureHigh();
            try {
            volume =  measureHigh * measureWidth * measureLong;
            }catch (Exception e){
            volume = 0;
            }
        }
        //重量
        BigDecimal div = NumberUtil.div(volume, carriageEntity.getLightThrowingCoefficient());
        //比较实际重量
        double max = NumberUtil.max(div.doubleValue(), carriageEntity.getFirstWeight());

        if (max <= 1){
            return 1;
        }
        if (max<=10){
            return NumberUtil.round(max,1).doubleValue();
        }
        if(max>=100){
            return NumberUtil.round(max,0).doubleValue();
        }
        double round = NumberUtil.round(max, 0, RoundingMode.DOWN).doubleValue();
        double v = max - round;
        if (v<=0.5){
            return NumberUtil.add(round, 0.5);
        }else {
            return NumberUtil.add(round, 1);
        }

    }
    public CarriageEntity findCarriageTemplate(WaybillDTO waybillDTO){
        Long senderCityId = waybillDTO.getSenderCityId();
        Long receiverCityId = waybillDTO.getReceiverCityId();
        if (cn.hutool.core.util.ObjectUtil.equals(senderCityId, receiverCityId)){
            CarriageEntity templateType = findByTemplateType(CarriageConstant.SAME_CITY);
            if (ObjectUtil.isEmpty(templateType)){
                return templateType;
            }
        }
        //查找省的同城模版
        Long senderParentId = areaFeign.get(senderCityId).getParentId();
        Long receiverParentId = areaFeign.get(receiverCityId).getParentId();
        if (cn.hutool.core.util.ObjectUtil.equals(senderParentId, receiverParentId)){
            CarriageEntity templateType = findByTemplateType(CarriageConstant.SAME_PROVINCE);
            if (ObjectUtil.isEmpty(templateType)){
                return templateType;
            }
        }
        //经济区互济
        CarriageEntity byEconomic = findByEconomic(senderParentId, receiverParentId);
        if (cn.hutool.core.util.ObjectUtil.isNotEmpty(byEconomic)){
            return byEconomic;
        }
        //跨省的模版
        CarriageEntity byTemplateType = findByTemplateType(CarriageConstant.TRANS_PROVINCE);
        if (cn.hutool.core.util.ObjectUtil.isNotEmpty(byTemplateType)){
            return byTemplateType;
        }
        throw new SLException(CarriageExceptionEnum.NOT_FOUND);


    }

    private CarriageEntity findByEconomic(Long senderParentId ,  Long receiverParentId){
        LinkedHashMap<String, EconomicRegionEnum> enumMap = EnumUtil.getEnumMap(EconomicRegionEnum.class);
        EconomicRegionEnum economicRegionEnum = null;
        for (EconomicRegionEnum regionEnum : enumMap.values()) {
            Long[] value = regionEnum.getValue();
            boolean b = ArrayUtil.containsAll(value, senderParentId, receiverParentId);
            if (b){
                economicRegionEnum = regionEnum;
                break;
            }
        }
        if (cn.hutool.core.util.ObjectUtil.isNull(economicRegionEnum)){
            return null;
        }
        CarriageEntity carriageEntity = this.getOne(Wrappers.<CarriageEntity>lambdaQuery()
                .eq(CarriageEntity::getTemplateType, CarriageConstant.ECONOMIC_ZONE)
                .like(CarriageEntity::getAssociatedCity, economicRegionEnum.getCode()));


        return carriageEntity;
    }

    @Override
    public CarriageEntity findByTemplateType(Integer templateType) {
        if(ObjectUtil.equals(CarriageConstant.ECONOMIC_ZONE, templateType)){
            throw  new SLException("经济区类型模版无法查询");
        }
        LambdaQueryWrapper<CarriageEntity> lambdaQueryWrapper = Wrappers.<CarriageEntity>lambdaQuery()
                .eq(CarriageEntity::getTemplateType, templateType);
        CarriageEntity carriageEntity = this.getOne(lambdaQueryWrapper);
        return carriageEntity;
    }
}
